package com.fudian.spark_platform.Configure

import net.minidev.json.{JSONArray, JSONObject}

import scala.collection.mutable
import scala.io.Source

class AppSettingConfig extends Serializable {

    var settings = mutable.Map(
        "AppName" -> "孚典Spark数据分析平台",
        "SparkMaster" -> "local[*]"
    )


    def setConf(appConf: JSONObject): AppSettingConfig = {
        val appKey = appConf.keySet()
        val iter = appKey.iterator()

        while (iter.hasNext) {
            val keyStr = iter.next()
            this.settings(keyStr) = appConf.get(keyStr).toString
        }
        this
    }
}

class DataSourceInputConfig extends Serializable {

    var inputConfig = mutable.Map(
        "DataSourceType" -> "textFile",
        "DataSourceLocation" -> "/Users/xiaojun/Desktop/开大个性化推荐报告/wechat_topic.csv",
        "DataSourceDelimiter" -> ",",
        //后期这个字段可以支持excel文件读取支持
        "DataSourceFileType" -> "csv",
        //uri目前暂时只用于mongodb的实现
        "DataSourceDBUri" -> "",
        //对于通用性数据库
        "DataSourceHost" -> "127.0.0.1",
        "DataSourcePort" -> "3306",
        "DataSourceUser" -> "root",
        "DataSourcePwd" -> "",
        "DataSourceDBName" -> "",
        //在mongodb中指代的是 collection
        "DataSourceDBTable" -> "",
        "DataSourceDBFds" -> Array(),
        //载入的数据量多少
        "DataSourceLimitCount" -> 0
    )

    def setConf(appConf: JSONObject): DataSourceInputConfig = {
        val appKey = appConf.keySet()
        val iter = appKey.iterator()

        while (iter.hasNext) {
            val keyStr = iter.next()
            keyStr match {
                case "DataSourceDBFds" => {
                    this.inputConfig("DataSourceDBFds") = appConf.get(keyStr)
                }
                case "DataSourceLimitCount" => {
                    this.inputConfig("DataSourceLimitCount") = appConf.getAsNumber(keyStr)
                }
                case _ => {
                    this.inputConfig(keyStr) = appConf.get(keyStr).toString
                }
            }
        }
        this
    }
}

class MillConfig extends Serializable {

    var millingConfig = mutable.Map(
        "ZHAble" -> false,
        "AllowNumber" -> false,
        "LimitCount" -> 2,
        "FastStopWords" -> "老师 谢谢 同学",
        "ZHStopWords" -> this.getDefaultStopWords("ZH"),
        "ENStopWords" -> this.getDefaultStopWords("EN"),
        "USStopWords" -> this.getDefaultStopWords("US")
    )


    def setConf(appConf: JSONObject): MillConfig = {
        val appKey = appConf.keySet()
        val iter = appKey.iterator()

        while (iter.hasNext) {
            val keyStr = iter.next()
            keyStr match {
                case "ZHAble" => {
                    this.millingConfig("ZHAble") = appConf.get(keyStr).asInstanceOf[Boolean]
                }
                case "AllowNumber" => {
                    this.millingConfig("AllowNumber") = appConf.get(keyStr).asInstanceOf[Boolean]
                }
                case "LimitCount" => {
                    this.millingConfig("LimitCount") = appConf.getAsNumber(keyStr)
                }
                case _ => {
                    this.millingConfig(keyStr) = appConf.get(keyStr).toString
                }
            }
        }
        this
    }


    /**
      * 获取统一的停用词文本词语
      *
      * @return
      */
    def getDefaultStopWords(stopType: String): Array[String] = {
        var tempArr = ""
        var resultsArr = Array("")
        stopType match {
            case "ZH" => {
                for (line <- Source.fromURL(this.getClass.getClassLoader.getResource("stopWords_zh.txt")).getLines()) {
                    tempArr = tempArr + " " + line
                }
                resultsArr = tempArr.split(" ")
            }
            case "EN" => {
                for (line <- Source.fromURL(this.getClass.getClassLoader.getResource("stopWords_en.txt")).getLines()) {
                    tempArr = tempArr + " " + line
                }
                resultsArr = tempArr.split(" ")
            }
            case "US" => {
                for (line <- Source.fromURL(this.getClass.getClassLoader.getResource("user_stop.txt")).getLines()) {
                    tempArr = tempArr + " " + line
                }
                resultsArr = tempArr.split(" ")
            }
        }
        resultsArr
    }
}

class TransformConfig extends Serializable {
    var transformConfig = mutable.Map(
        "TransformType" -> "CountVector",
        "CountVector" -> mutable.Map(
            "InputCol" -> "words",
            "OutPutCol" -> "feature"
        ),
        "HashingTF" -> mutable.Map(
            "InputCol" -> "words",
            "OutPutCol" -> "feature"
        ),
        "InputCol" -> "words",
        "OutPutCol" -> "feature",
        "minDF"->2
    )

    def setConf(appConf: JSONObject): TransformConfig = {
        val appKey = appConf.keySet()
        val iter = appKey.iterator()

        while (iter.hasNext) {
            val keyStr = iter.next()
            this.transformConfig(keyStr) = appConf.get(keyStr).toString
        }
        this
    }

}

class MLConfig extends Serializable {
    var mLConfig = mutable.Map(
        "LDA" -> mutable.Map(
            "k" -> "3",
            "maxItNum" -> "20",
            "optimizer" -> "em",
            "describeTopics" -> "10"
        ),

        "TF_IDF" -> mutable.Map(
            "minDoc" -> "2",
            "inputCol" -> "features",
            "outputCol" -> "idf"
        ),

        "K_Means" -> mutable.Map(
            "k" -> "6",
            "maxItNum" -> "50",
            "seed" -> "1"
        ),

        "ALS" -> mutable.Map(
            "k" -> "10",
            "maxItNum" -> "30",
            "regParam" -> "0.01",
            "implicitPrefs" -> true,
            "userCol" -> "indicesSid",
            "itemCol" -> "indicesCid",
            "ratingCol" -> "rating"
        ),

        "Word2Vector" -> mutable.Map(),
        "MLParams" -> mutable.Map(),
        "MLType" -> "LDA"
    )

    def setConf(appConf: JSONObject): MLConfig = {

        val appKey = appConf.keySet()
        val iter = appKey.iterator()
        var mlType = ""
        while (iter.hasNext) {
            val keyStr = iter.next()
            if(keyStr == "MLType"){
                mlType = appConf.get(keyStr).toString
            }else{
                val LDAPars = appConf.get(keyStr).asInstanceOf[JSONObject]
                val Params = this.mLConfig(keyStr).asInstanceOf[mutable.Map[String, Any]]
                //遍历传递的LDA参数,覆盖默认参数
                val ldaKey = LDAPars.keySet()
                val ldaIter = ldaKey.iterator()
                while (ldaIter.hasNext) {
                    val ldaInstance = ldaIter.next()
                    Params(ldaInstance) = LDAPars.getOrDefault(ldaInstance, Params(ldaInstance).toString)
                }
                this.mLConfig("MLParams") = Params
                this.mLConfig("MLType") = keyStr
            }
        }
        this.mLConfig("MLType") = mlType
        this
    }
}

class OutputConfig extends Serializable {

    var outConfig = mutable.Map(
        "OutputType" -> "console",
        //文本输出配置
        "OutTextPath" -> "",
        //数据库数据配置
        "OutDataBaseType" -> "",
        "OutDataBaseName" -> "",
        "OutDataBaseHost" -> "",
        "OutDataBasePort" -> "",
        "OutDataBaseTable" -> "",
        "OutDataBaseFds" -> "id results",
        "OutDataBaseUser" -> "",
        "OutDataBasePwd" -> "",
        //hdfs输出配置
        "OutHDFSPath" -> ""
    )

    def setConf(appConf: JSONObject): OutputConfig = {

        val appKey = appConf.keySet()
        val iter = appKey.iterator()

        while (iter.hasNext) {
            val keyStr = iter.next()
            keyStr match {
                case "OutDataBaseFds" => {
                    this.outConfig("OutDataBaseFds") = appConf.get(keyStr).toString
                }
                case _ => {
                    this.outConfig(keyStr) = appConf.get(keyStr).toString
                }
            }
        }
        this
    }

}

